package com.mastercard.labs

import grails.converters.JSON
import org.springframework.dao.DataIntegrityViolationException
import org.apache.shiro.SecurityUtils

class TransactionController {

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

	def transactionService
	def rewardPointService
	def cardService
	def exportService
	def grailsApplication  //inject GrailsApplication

    def index() {
        redirect(action: "list", params: params)
    }

    def list() {
        params.max = Math.min(params.max ? params.int('max') : 10, 100)
		if(params?.format && params.format != "html"){
			params.max=100
			
			response.contentType = grailsApplication.config.grails.mime.types[params.format]
			response.setHeader("Content-disposition", "attachment; filename=Past_Transaction.${params.format}")


			List fields = ["merchant", "card", "amount", "txnDate", "description"]
			Map labels = ["merchant":"Merchant", "card":"Card", "amount":"Amount", "txnDate":"Date", "description":"Description"]

						/* Formatter closure in previous releases
			def upperCase = { value ->
				return value.toUpperCase()
			}
			*/

						// Formatter closure
			def merchantFmt = { domain, value ->
				return domain?.merchant.name
			}
			
			def cardFmt = { domain, value ->
				return domain?.card.getMaskNumber()
			}

			Map formatters = [merchant: merchantFmt, card:cardFmt]
			Map parameters = [title: "Past Transactions", "column.widths": [0.2, 0.2, 0.2, 0.2, 0.2]]
			
			params.sort="txnDate"
			params.order="desc"
			exportService.export(params.format, response.outputStream, Transaction.list(params), fields, labels, formatters, parameters)
		}
		
        [transactionInstanceList: Transaction.list(params), transactionInstanceTotal: Transaction.count()]
    }

    def create() {
        [transactionInstance: new Transaction(params)]
    }

    def save() {
        def transactionInstance = new Transaction(params)
		def user = cardService.getUser(transactionInstance.card)
		transactionInstance.user = user
        if (!transactionInstance.save(flush: true)) {
            render(view: "create", model: [transactionInstance: transactionInstance])
            return
        }
		transactionService.postTransaction(transactionInstance, user)
		flash.message = message(code: 'default.created.message', args: [message(code: 'transaction.label', default: 'Transaction'), transactionInstance.id])
        redirect(action: "show", id: transactionInstance.id)
    }

    def show() {
        def transactionInstance = Transaction.get(params.id)
        if (!transactionInstance) {
			flash.message = message(code: 'default.not.found.message', args: [message(code: 'transaction.label', default: 'Transaction'), params.id])
            redirect(action: "list")
            return
        }

        [transactionInstance: transactionInstance]
    }

    def edit() {
        def transactionInstance = Transaction.get(params.id)
        if (!transactionInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'transaction.label', default: 'Transaction'), params.id])
            redirect(action: "list")
            return
        }

        [transactionInstance: transactionInstance]
    }

    def update() {
        def transactionInstance = Transaction.get(params.id)
        if (!transactionInstance) {
            flash.message = message(code: 'default.not.found.message', args: [message(code: 'transaction.label', default: 'Transaction'), params.id])
            redirect(action: "list")
            return
        }

        if (params.version) {
            def version = params.version.toLong()
            if (transactionInstance.version > version) {
                transactionInstance.errors.rejectValue("version", "default.optimistic.locking.failure",
                          [message(code: 'transaction.label', default: 'Transaction')] as Object[],
                          "Another user has updated this Transaction while you were editing")
                render(view: "edit", model: [transactionInstance: transactionInstance])
                return
            }
        }

        transactionInstance.properties = params

        if (!transactionInstance.save(flush: true)) {
            render(view: "edit", model: [transactionInstance: transactionInstance])
            return
        }

		flash.message = message(code: 'default.updated.message', args: [message(code: 'transaction.label', default: 'Transaction'), transactionInstance.id])
        redirect(action: "show", id: transactionInstance.id)
    }

    def delete() {
        def transactionInstance = Transaction.get(params.id)
        if (!transactionInstance) {
			flash.message = message(code: 'default.not.found.message', args: [message(code: 'transaction.label', default: 'Transaction'), params.id])
            redirect(action: "list")
            return
        }

        try {
            transactionInstance.delete(flush: true)
			flash.message = message(code: 'default.deleted.message', args: [message(code: 'transaction.label', default: 'Transaction'), params.id])
            redirect(action: "list")
        }
        catch (DataIntegrityViolationException e) {
			flash.message = message(code: 'default.not.deleted.message', args: [message(code: 'transaction.label', default: 'Transaction'), params.id])
            redirect(action: "show", id: params.id)
        }
    }
	
	def getTransactionsJSON() {
		Calendar cal = Calendar.getInstance()
		cal.set(2012, 1, 1);
		Date fromDate = cal.getTime()
		render (text: new JSON(transactionService.getTransactions(fromDate, new Date())),
			contentType:"application/json")
	}
	
	def setDescription() {
		def transaction = Transaction.get(params.id)
		transaction.description = params.description
		transaction.save()
		render (text: new JSON(transaction))
	}
	
	def getCategorySpending() {
		def user = SecurityUtils.subject.session.getAttribute("current_user")
		Calendar cal = Calendar.getInstance()
		cal.set(2012, 0, 1);
		Date fromDate = cal.getTime()
		cal.set(2012, 9, 1)
		Date toDate = cal.getTime()

		render (text: new JSON(transactionService.getCategorySpending(user, fromDate, toDate)))
	}
	
	def getSummary() {
		def user = SecurityUtils.subject.session.getAttribute("current_user")
		render (text: new JSON(transactionService.getSummary(user)))
	}
}
